#include "data_proc.h"
#include <QDebug>
#include <chrono>
#include <thread>
DATA_PROC::DATA_PROC()
{

}

/* 计算检验码
 * 输入：指令
 * 输出：校验码
 */
std::pair<uint8_t, uint8_t> DATA_PROC::calculateChecksum(const std::vector<uint8_t>& data) {
    size_t length = data.size();
    uint16_t sum = 0;
    for (size_t i = 0; i < length; i++) {
        sum += data[i];
    }
    // 取反并加1，注意这里处理的是16位整数，因此结果可能跨越两个字节
    uint16_t inverted_sum = ~sum;
    uint16_t checksum = inverted_sum + 1;
    // 提取低字节和高字节
    uint8_t low_byte = static_cast<uint8_t>(checksum & 0xFF);
    uint8_t high_byte;
    if(sum > 0xff)
    {
        high_byte = static_cast<uint8_t>((checksum >> 8) & 0xFF);
    }
    else
    {
        high_byte = 0x00;
    }
    return {low_byte, high_byte};
}

/*
 * 检测接收到的指令
 * 输入：从rs422读到的指令
 * 输出：信息缩写
 */
std::pair<uint8_t, uint8_t> DATA_PROC::getInfoFromReceived(const std::vector<uint8_t>& data){

    std::vector<uint8_t> pre_data = data;
    pre_data.erase(pre_data.begin());
    pre_data.erase(pre_data.end() - 4, pre_data.end());
    std::pair<uint8_t, uint8_t> checksum = this->calculateChecksum(pre_data);
    qDebug() << "checksum:" << checksum;
    int length = data.size();
    if ((checksum.first != data[length - 4]) | (checksum.second != data[length - 3]))
    {
        qDebug() << "数据校验码错误";
        return {-1, -1};
    }

    switch (data[1]) {
    case 0xf0:
        qDebug() << "握手请求";
        return {rxClass::HandShakeRequst, 0};
    case 0xf3:
        qDebug() << "自检信息";
        return {rxClass::SelfCheckInfo, data[3]};
    case 0xf5:
        qDebug() << "时间设置反馈";
        return {rxClass::InputParameter, data[3]};
    case 0xf7:
        qDebug() << "时间装订信反馈";
        return {rxClass::TimeAligned, data[3]};
    default:
        qDebug() << "未知指令";
        return {-1, 0};
    }
}
/*
 * 反馈主控的握手请求
 */
QByteArray DATA_PROC::data4responseHandShake(void)
{
    std::vector<uint8_t> send = {0xdd, 0xf1, 0x00, 0x0f, 0x00, 0x0d, 0x0a};
    return Vector2QByteArray(send);
}
/*
 * 请求自检信息
 */
QByteArray DATA_PROC::data4selfCheckInfo()
{
    std::vector<uint8_t> pre_data = {0xdd, 0xf2, 0x00};
    return Vector2QByteArray(fillSendData(pre_data));
}
/*
 * 输入预置参数
 */
QByteArray DATA_PROC::data4inputPresetParameter(bool isRelative, uint32_t time)
{
    std::vector<uint8_t> pre_data = {0xdd, 0xf4, 0x05};
    // 相对时间
    if(isRelative)
    {
        pre_data.emplace_back(0x01);
    }
    // 绝对时间
    else
    {
        pre_data.emplace_back(0x02);
    }
    uint8_t t_31_24 = (time >> 24) & 0xff;
    uint8_t t_23_16 = (time >> 16) & 0xff;
    uint8_t t_15_8 = (time >> 8) & 0xff;
    uint8_t t_7_0 = time & 0xff;
    pre_data.emplace_back(t_7_0);
    pre_data.emplace_back(t_15_8);
    pre_data.emplace_back(t_23_16);
    pre_data.emplace_back(t_31_24);

    return Vector2QByteArray(fillSendData(pre_data));

}
/*
 * 校准时间
 */
QByteArray DATA_PROC::data4timeAlign(uint32_t time)
{
    std::vector<uint8_t> pre_data = {0xdd, 0xf6, 0x04};
    uint8_t t_31_24 = (time >> 24) & 0xff;
    uint8_t t_23_16 = (time >> 16) & 0xff;
    uint8_t t_15_8 = (time >> 8) & 0xff;
    uint8_t t_7_0 = time & 0xff;
    pre_data.emplace_back(t_7_0);
    pre_data.emplace_back(t_15_8);
    pre_data.emplace_back(t_23_16);
    pre_data.emplace_back(t_31_24);

    return Vector2QByteArray(fillSendData(pre_data));

}
QByteArray DATA_PROC::stdString2Hex(std::string str)
{
    QString qstr = QString::fromStdString(str);
    QByteArray hex;
    for (int i = 0; i < qstr.length(); i += 2) {
        QString byteStr = qstr.mid(i, 2);
        bool ok;
        char byte = static_cast<char>(byteStr.toInt(&ok, 16));
        if (ok) {
            hex.append(byte);
        } else {
            qDebug() << "Invalid hex string";
        }
    }
    return hex;
}
/*
 * QByteArray2Vector
 */
std::vector<uint8_t> DATA_PROC::QByteArray2Vector(const QByteArray& byteArray) {
    std::vector<uint8_t> vec(byteArray.size());
    std::copy(byteArray.constData(), byteArray.constData() + byteArray.size(), vec.begin());
    return vec;
}
/*
 * Vector2QByteArray
 */
QByteArray DATA_PROC::Vector2QByteArray(const std::vector<uint8_t>& vec) {
    QByteArray byteArray;
    byteArray.resize(vec.size());

    std::copy(vec.begin(), vec.end(), reinterpret_cast<uint8_t*>(byteArray.data()));

    return byteArray;
}
void DATA_PROC::delay(int milliseconds)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
/*
 * 利用报头和信息数据，增加校验和报尾
 */
std::vector<uint8_t> DATA_PROC::fillSendData(std::vector<uint8_t> &pre_data)
{
    std::vector<uint8_t> data = pre_data;
    data.erase(data.begin());
    std::pair<uint8_t, uint8_t> checksum = calculateChecksum(data);
    data.emplace_back(checksum.first);
    data.emplace_back(checksum.second);
    data.emplace_back(0x0d);
    data.emplace_back(0x0a);
    data.insert(data.begin(), pre_data[0]);

    return data;
}

